<template>
  <view>
    <slot></slot>
    <view class="overflow fixed" style=" left: -999px">
      <!-- #ifdef APP-NVUE -->
      <gcanvas id="waterCanvas" ref="waterCanvasRef"
               :style="{ width: `${boxInfo.width}${props.unit}`, height: `${boxInfo.height}${props.unit}` }"></gcanvas>
      <!-- #endif -->
      <!-- #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ -->
      <canvas id="waterCanvas" type="2d"
              :style="{ width: `${boxInfo.width}${props.unit}`, height: `${boxInfo.height}${props.unit}` }"></canvas>
      <!-- #endif -->
      <!-- #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ || APP-NVUE -->
      <canvas id="waterCanvas" canvas-id="waterCanvas"
              :style="{ width: `${boxInfo.width}${props.unit}`, height: `${boxInfo.height}${props.unit}` }"></canvas>
      <!-- #endif -->
    </view>

    <view :class="props.fullscreen ? 'fixed' : 'absolute'" :style="imageWaterStyle"></view>
  </view>
</template>
<script lang="ts" setup>
/**
 * 水印
 * 给页面或者 组件添加水印。
 */
import {computed, getCurrentInstance, nextTick, onMounted, ref, watch, watchEffect} from "vue";

const props = defineProps({
  cross: Boolean,
  debug: Boolean,
  fullscreen: Boolean,
  width: {
    type: Number,
    default: 64
  }, height: {
    type: Number,
    default: 64
  }, zIndex: {
    type: Number,
    default: 999
  }, xGap: {
    type: Number,
    default: 0
  }, yGap: {
    type: Number,
    default: 0
  }, yOffset: {
    type: Number,
    default: 0
  }, xOffset: {
    type: Number,
    default: 0
  }, rotate: {
    type: Number,
    default: 0
  }, image: String,
  imageOpacity: {type: Number, default: 1},
  imageHeight: Number,
  imageWidth: Number,
  content: String,
  selectable: {
    type: Boolean,
    default: true
  }, fontSize: {
    type: Number,
    default: 14
  },
  fontFamily: String,
  fontStyle: {
    type: String,
    default: 'normal'
  }, fontVariant: {
    type: String,
    default: ''
  }, fontWeight: {
    type: Number,
    default: 400
  }, fontColor: {
    type: String,
    default: 'rgba(128, 128, 128, .3)'
  }, fontStretch: {
    type: String,
    default: ''
  }, lineHeight: {
    type: Number,
    default: 14
  }, unit: {
    type: String,
    default: 'rpx'
  }
});

// #ifdef APP-NVUE
import {enable, WeexBridge} from '../../tool/gcanvas/index.js';
import {qr} from "../tm-qrcode/drawing";
// #endif
const {proxy}: any = getCurrentInstance();
const waterCanvasRef = ref();
const boxInfo = ref({width: props.width, height: props.height});
const base64UrlRef = ref();
const imageWaterStyle = computed(() => {
  return {
    zIndex: props.zIndex,
    width: '100%',
    height: '100%',
    pointerEvents: 'none',
    backgroundRepeat: 'repeat',
    top: 0,
    left: 0,
    backgroundSize: props.unit == 'rpx' ? `${uni.upx2px(props.xGap + props.width)} px` : `${props.xGap + props.width} px`,
    backgroundPosition: props.cross
        ? `${props.unit == 'rpx' ? uni.upx2px(props.width / 2) : (props.width / 2)}px ${props.unit == 'rpx' ? uni.upx2px(props.height / 2) : (props.height / 2)}px, 0 0`
        : '',
    backgroundImage: props.cross
        ? `url(${base64UrlRef.value}), url(${base64UrlRef.value})`
        : `url(${base64UrlRef.value})`
  }
})

onMounted( () => {
  nextTick(async function () {
    await init();
  })

});
watch(()=>props,async () => {
  await init();
},{deep:true})

async function init() {
  // #ifdef APP-NVUE
  const canvas = enable(waterCanvasRef.value, {
    bridge: WeexBridge
  });
  const ctx = canvas.getContext('2d');
  // #endif
  // #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
  const {ctx, canvas}: any = await mp_init();
  // #endif
  // #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ || APP-NVUE
  const ctx = uni.createCanvasContext("waterCanvas", proxy),canvas=null;
  // #endif
  const ratio = uni.getSystemInfoSync().pixelRatio
  const {
    xGap,
    yGap,
    width,
    height,
    yOffset,
    xOffset,
    rotate,
    image,
    content,
    fontColor,
    fontStyle,
    fontVariant,
    fontStretch,
    fontWeight,
    fontFamily,
    fontSize,
    lineHeight,
    debug
  } = props;

  const canvasWidth = (xGap + (width > 0 ? width : 1)) * ratio;
  const canvasHeight = (yGap + (height > 0 ? height : 1)) * ratio;
  const canvasOffsetLeft = props.unit == 'rpx' ? uni.upx2px(xOffset * ratio) : xOffset * ratio;
  const canvasOffsetTop = props.unit == 'rpx' ? uni.upx2px(yOffset * ratio) : yOffset * ratio;
  const canvasWidthPx = props.unit == 'rpx' ? uni.upx2px(canvasWidth) : canvasWidth;
  const canvasHeightPx = props.unit == 'rpx' ? uni.upx2px(canvasHeight) : canvasHeight;
  boxInfo.value = {width: canvasWidth, height: canvasHeight}

  // #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
  canvas.width = canvasWidthPx;
  canvas.height = canvasHeightPx;
  // #endif

  if (ctx) {
    ctx.translate(0, 0);
    const markWidth = props.unit == 'rpx' ? uni.upx2px(width * ratio) : (width * ratio);
    const markHeight = props.unit == 'rpx' ? uni.upx2px(height * ratio) : (height * ratio);
    if (debug) {
      ctx.strokeStyle = 'grey';
      ctx.strokeRect(0, 0, markWidth, markHeight);
    }
    ctx.rotate(rotate * (Math.PI / 180));
    if (image) {

          const {imageWidth, imageHeight} = props;
          // #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
          const imageObj = canvas.createImage();
          imageObj.crossOrigin = 'anonymous';
          imageObj.referrerPolicy = 'no-referrer';
          imageObj.src = image;
          imageObj.onload = () => {
            ctx.globalAlpha = props.imageOpacity;
            ctx.drawImage(imageObj, canvasOffsetLeft, canvasOffsetTop,(props.imageWidth ||
                (imageHeight
                    ? (imageObj.width * imageHeight) / imageObj.height
                    : imageObj.width)) * ratio, (props.imageHeight ||
                (imageWidth
                    ? (imageObj.height * imageWidth) / imageObj.width
                    : imageObj.height)) * ratio);
            endInit({ctx: ctx, canvas: canvas ?? null, canvasWidthPx: canvasWidthPx, canvasHeightPx: canvasHeightPx});
          }
          // #endif
          // #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ
      await uni.getImageInfo({
        src: image,
        success: function (img) {
          ctx.globalAlpha = props.imageOpacity;
          ctx.drawImage(image, canvasOffsetLeft, canvasOffsetTop, (props.imageWidth ||
              (imageHeight
                  ? (img.width * imageHeight) / img.height
                  : img.width)) * ratio, (props.imageHeight ||
              (imageWidth
                  ? (img.height * imageWidth) / img.width
                  : img.height)) * ratio);
          endInit({ctx: ctx, canvas: canvas, canvasWidthPx: canvasWidthPx, canvasHeightPx: canvasHeightPx});
        }
      });
          // #endif


    } else if (content) {
      if (debug) {
        ctx.strokeStyle = 'green';
        ctx.strokeRect(0, 0, markWidth, markHeight);
      }
      const fontSizePx = props.unit == 'rpx' ? uni.upx2px(fontSize * ratio) : (fontSize * ratio);

      const fontLineHeightPx = props.unit == 'rpx' ? uni.upx2px(lineHeight * ratio) : (lineHeight * ratio);
      const ySize = props.unit == 'rpx' ? uni.upx2px(canvasOffsetTop + lineHeight * ratio) : (canvasOffsetTop + lineHeight * ratio);
      ctx.font = `${fontStyle} ${fontWeight} ${fontSizePx}px/${fontLineHeightPx}px ${fontStretch} ${fontVariant} ${fontFamily || 'sans-serif'}`;
      ctx.fillStyle = fontColor;
      ctx.fillText(content, canvasOffsetLeft, ySize);
      endInit({ctx: ctx, canvas: canvas, canvasWidthPx: canvasWidthPx, canvasHeightPx: canvasHeightPx});
    }

  } else {

  }
}
function endInit({
                   ctx,
                   canvas,
                   canvasWidthPx,
                   canvasHeightPx
                 }: { ctx: any, canvas: any, canvasWidthPx: any, canvasHeightPx: any }){
  // #ifdef APP-NVUE
  ctx.draw(false,()=> {
    ctx.toTempFilePath(0, 0, canvasWidthPx, canvasHeightPx, canvasWidthPx, canvasHeightPx, "png", 1, function (res: { errMsg: string; tempFilePath: any; }) {
      base64UrlRef.value = res.tempFilePath;
    })
  });
  // #endif
  // #ifndef APP-NVUE ||  MP-WEIXIN || MP-ALIPAY || MP-QQ
  ctx.draw(false,()=>{
    uni.canvasToTempFilePath({
      width:canvasWidthPx,
      height:canvasHeightPx,
      destWidth: canvasWidthPx,
      destHeight: canvasHeightPx,
      canvasId: 'waterCanvas',
      success: function (res) {
        base64UrlRef.value = res.tempFilePath;
      }
    })
  });

  // #endif
  // #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
  base64UrlRef.value = canvas.toDataURL();
  // #endif
}
//支付宝和微信，QQ 支持2d渲染。
function mp_init() {
  return new Promise((resolve, rej) => {
    const query = uni.createSelectorQuery().in(proxy)
    query.select('#waterCanvas')
        .fields({
          node: true,
          size: true
        })
        .exec((res) => {
          const canvas = res[0].node
          const ctx = canvas.getContext('2d')
          const dpr = uni.getSystemInfoSync().pixelRatio
          canvas.width = res[0].width * dpr
          canvas.height = res[0].height * dpr
          ctx.scale(dpr, dpr)
          resolve({ctx, canvas})
        })
  })
}
</script>